package service

import (
	"bloggo/bloggo"
	"bloggo/structs"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/chunanyong/logger"
	"gitee.com/chunanyong/zorm"
	"strconv"
	"time"
)

const CacheTag = bloggo.CacheKey + structs.TbTagStructTableName + ":"

//SaveTbTagStruct 保存
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func SaveTbTagStruct(ctx context.Context, tbtagstruct *structs.TbTagStruct) error {

	// tbtagstruct对象指针不能为空
	if tbtagstruct == nil {
		return errors.New("tbtagstruct对象指针不能为空")
	}
	finder := zorm.NewSelectFinder(structs.TbTagStructTableName).Append("WHERE tag_name=?", tbtagstruct.TagName)
	var temp structs.TbTagStruct
	row, _ := zorm.QueryRow(ctx, finder, &temp)
	if row {
		return nil
	}
	tbtagstruct.CreateTime = time.Now()
	tbtagstruct.UpdateTime = time.Now()
	//匿名函数return的error如果不为nil,事务就会回滚
	_, errSaveTbTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始

		_, errSaveTbTagStruct := zorm.Insert(ctx, tbtagstruct)

		if errSaveTbTagStruct != nil {
			return nil, errSaveTbTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errSaveTbTagStruct != nil {
		errSaveTbTagStruct := fmt.Errorf("service.SaveTbTagStruct错误:%w", errSaveTbTagStruct)
		logger.Error(errSaveTbTagStruct)
		return errSaveTbTagStruct
	}

	return nil
}

//UpdateTbTagStruct 更新
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func UpdateTbTagStruct(ctx context.Context, tbtagstruct *structs.TbTagStruct) error {

	// tbtagstruct对象指针或主键Id不能为空
	if tbtagstruct == nil || (tbtagstruct.Id) < 1 {
		return errors.New("tbtagstruct对象指针或主键Id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errUpdateTbTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		_, errUpdateTbTagStruct := zorm.Update(ctx, tbtagstruct)

		if errUpdateTbTagStruct != nil {
			return nil, errUpdateTbTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errUpdateTbTagStruct != nil {
		errUpdateTbTagStruct := fmt.Errorf("service.UpdateTbTagStruct错误:%w", errUpdateTbTagStruct)
		logger.Error(errUpdateTbTagStruct)
		return errUpdateTbTagStruct
	}
	bloggo.Del(CacheTag + strconv.Itoa(tbtagstruct.Id))
	return nil
}

//UpdateNotZeroTbTagStruct 更新
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func UpdateNotZeroTbTagStruct(ctx context.Context, tbtagstruct *structs.TbTagStruct) error {

	// tbtagstruct对象指针或主键Id不能为空
	if tbtagstruct == nil || (tbtagstruct.Id) < 1 {
		return errors.New("tbtagstruct对象指针或主键Id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errUpdateTbTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		_, errUpdateTbTagStruct := zorm.UpdateNotZeroValue(ctx, tbtagstruct)

		if errUpdateTbTagStruct != nil {
			return nil, errUpdateTbTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errUpdateTbTagStruct != nil {
		errUpdateTbTagStruct := fmt.Errorf("service.UpdateNotZeroTbTagStruct错误:%w", errUpdateTbTagStruct)
		logger.Error(errUpdateTbTagStruct)
		return errUpdateTbTagStruct
	}
	bloggo.Del(CacheTag + strconv.Itoa(tbtagstruct.Id))
	return nil
}

//DeleteTbTagStructById 根据Id删除
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func DeleteTbTagStructById(ctx context.Context, id string) error {

	//id不能为空
	if len(id) < 1 {
		return errors.New("id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errDeleteTbTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		finder := zorm.NewDeleteFinder(structs.TbTagStructTableName).Append(" WHERE id=?", id)
		_, errDeleteTbTagStruct := zorm.UpdateFinder(ctx, finder)

		if errDeleteTbTagStruct != nil {
			return nil, errDeleteTbTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errDeleteTbTagStruct != nil {
		errDeleteTbTagStruct := fmt.Errorf("service.DeleteTbTagStruct错误:%w", errDeleteTbTagStruct)
		logger.Error(errDeleteTbTagStruct)
		return errDeleteTbTagStruct
	}
	bloggo.Del(CacheTag + id)
	return nil
}

//FindTbTagStructById 根据Id查询信息
//ctx中如果没有dbConnection,则会使用默认的datasource进行无事务查询
func FindTbTagStructById(ctx context.Context, id string) (*structs.TbTagStruct, error) {
	//id不能为空
	if len(id) < 1 {
		return nil, errors.New("id不能为空")
	}
	bytes, _ := bloggo.Get(CacheTag + id)
	tbtagstruct := structs.TbTagStruct{}
	err := json.Unmarshal(bytes, &tbtagstruct)
	if err == nil {
		return &tbtagstruct, nil
	}
	//根据Id查询
	finder := zorm.NewSelectFinder(structs.TbTagStructTableName).Append(" WHERE id=?", id)
	has, errFindTbTagStructById := zorm.QueryRow(ctx, finder, &tbtagstruct)

	//记录错误
	if errFindTbTagStructById != nil {
		errFindTbTagStructById := fmt.Errorf("service.FindTbTagStructById错误:%w", errFindTbTagStructById)
		logger.Error(errFindTbTagStructById)
		return nil, errFindTbTagStructById
	}

	if !has {
		return nil, nil
	}
	bytes, err = json.Marshal(tbtagstruct)
	if err == nil {
		bloggo.Set(CacheTag+id, bytes)
	}
	return &tbtagstruct, nil

}

//FindTbTagStructList 根据Finder查询列表
//ctx中如果没有dbConnection,则会使用默认的datasource进行无事务查询
func FindTbTagStructList(ctx context.Context, finder *zorm.Finder, page *zorm.Page) ([]structs.TbTagStruct, error) {

	//finder不能为空
	if finder == nil {
		return nil, errors.New("finder不能为空")
	}

	tbtagstructList := make([]structs.TbTagStruct, 0)
	errFindTbTagStructList := zorm.Query(ctx, finder, &tbtagstructList, page)

	//记录错误
	if errFindTbTagStructList != nil {
		errFindTbTagStructList := fmt.Errorf("service.FindTbTagStructList错误:%w", errFindTbTagStructList)
		logger.Error(errFindTbTagStructList)
		return nil, errFindTbTagStructList
	}

	return tbtagstructList, nil
}

func FindeTagIdsByNames(names []string) (ids []int, err error) {
	finder := zorm.NewSelectFinder(structs.TbTagStructTableName, "id").Append("WHERE tag_name in (?)", names)
	err = zorm.Query(context.Background(), finder, &ids, nil)
	if err != nil {
		return nil, err
	}
	return ids, err
}
